<template>
  <div ref="canvasContainer" class="canvas-container"></div>
  <button @click="downloadCanvas" class="download-btn">下载画布</button>
</template>

<script>
  import * as THREE from "three";
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
  // 添加CSS2D渲染器
  import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

  import imgUrl1 from '@/assets/img/5.jpg';

  import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

  export default {
    name: "",
    components: {
    },
    computed: {},
    data() {
      return {

      };
    },
    mounted() {
      // 初始化场景、相机、渲染器等
      this.initScene();
      // 创建管道
      this.createTube()

      this.animate();
      this.createControls()
      // 窗口大小自适应
      window.addEventListener('resize', this.onWindowResize)
    },
    methods: {
      downloadCanvas() {
        // 1. 创建临时链接
        const link = document.createElement('a');

        // 2. 将渲染器的画布转换为DataURL
        link.href = this.renderer.domElement.toDataURL('image/png');

        // 3. 设置下载文件名
        link.download = 'threejs-canvas.png';

        // 4. 触发点击下载
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      },
      async createTube() {
        // 创建四个三维向量点，用于定义贝塞尔曲线
        const p1 = new THREE.Vector3(-100, 0, 0);   // 起点：x=-100, y=0, z=0
        const p2 = new THREE.Vector3(50, 100, 0);   // 第一个控制点：x=50, y=100, z=0
        const p3 = new THREE.Vector3(100, 0, 100);  // 第二个控制点：x=100, y=0, z=100
        const p4 = new THREE.Vector3(100, 0, 0);    // 终点：x=100, y=0, z=0

        const curve = new THREE.CubicBezierCurve3(p1, p2, p3, p4);

        const geometry = new THREE.TubeGeometry(curve, 50, 20, 20);

        const materail = new THREE.MeshLambertMaterial({
          color: new THREE.Color('orange'),
          side: THREE.DoubleSide,
        });

        const mesh = new THREE.Mesh(geometry, materail);

        // 创建控制面板
        const gui = new GUI();

        const obj = {
          tubularSegments: 50,
          radius: 20,
          radialSegments: 20
        }
        function onChange() {
          mesh.geometry = new THREE.TubeGeometry(
            curve,
            obj.tubularSegments,
            obj.radius,
            obj.radialSegments
          );
        }
        gui.add(obj, 'tubularSegments').onChange(onChange)
          .min(3).max(100).step(1).name('管道方向分段数');
        gui.add(obj, 'radius').onChange(onChange)
          .min(10).max(100).step(0.1).name('半径');
        gui.add(obj, 'radialSegments').onChange(onChange)
          .min(3).max(100).step(1).name('横截面分段数');


        const geometry2 = new THREE.BufferGeometry();
        geometry2.setFromPoints([p1, p2, p3, p4]);
        const material2 = new THREE.PointsMaterial({
          color: new THREE.Color('blue'),
          size: 10
        });

        const points2 = new THREE.Points(geometry2, material2);
        const line2 = new THREE.Line(geometry2, new THREE.LineBasicMaterial());
        mesh.add(points2, line2);

        this.scene.add(mesh);

      },
      initScene() {
        // 1. 创建场景
        this.scene = new THREE.Scene()
        // 设置场景背景色为灰色
        this.scene.background = new THREE.Color(0x27304D);

        // 2. 创建相机（透视相机）
        this.camera = new THREE.PerspectiveCamera(
          75,  // 1. 视野角度(FOV - Field of View)- 单位是度(°)，表示相机垂直方向的视野范围。值越大，看到的场景越多(类似广角镜头)；值越小，看到的场景越少(类似长焦镜头)。通常设置在45-75度之间。
          window.innerWidth / window.innerHeight, // 2. 宽高比(aspect ratio)- 通常设置为渲染区域的宽度除以高度(如窗口宽高比)。这个值影响水平方向的视野。
          0.1, // 3. 近裁剪面(near clipping plane)- 相机能看到的最近距离。小于这个距离的物体不会被渲染。通常设置为一个较小的正数(如0.1)。
          1000 // 4. 远裁剪面(far clipping plane) - 相机能看到的最远距离。大于这个距离的物体不会被渲染。根据场景大小设置适当的值。
        );
        this.camera.position.x = 30
        // lookAt()方法可以让相机指向一个特定的点，它会受OrbitControls影响
        // this.camera.lookAt(5, 0, 0);

        // 3. 创建渲染器
        this.renderer = new THREE.WebGLRenderer({
          antialias: true,
          alpha: true,
          preserveDrawingBuffer: true // 添加此项确保可以捕获画布内容
        });
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.setSize(window.innerWidth, window.innerHeight)
        // 4. 挂载到DOM
        this.$refs.canvasContainer.appendChild(this.renderer.domElement)

        // 添加环境光和方向光
        const ambientLight = new THREE.AmbientLight(0xffffff, 2);
        this.scene.add(ambientLight);

        // 增强平行光强度和添加辅助光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.position.set(10, 20, 10);
        directionalLight.castShadow = true;
        this.scene.add(directionalLight);

        // 添加第二个辅助平行光
        const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight2.position.set(-10, 20, -10);
        this.scene.add(directionalLight2);

        // 添加半球光模拟环境反射
        const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
        hemisphereLight.position.set(0, 20, 0);
        this.scene.add(hemisphereLight);


        // 创建CSS2D渲染器
        this.labelRenderer = new CSS2DRenderer();
        this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
        this.labelRenderer.domElement.style.position = 'absolute';
        this.labelRenderer.domElement.style.top = '0';
        this.labelRenderer.domElement.style.pointerEvents = 'none';
        this.$refs.canvasContainer.appendChild(this.labelRenderer.domElement);
      },
      // 动画循环
      animate() {
        requestAnimationFrame(this.animate)
        this.renderer.render(this.scene, this.camera)
        this.labelRenderer.render(this.scene, this.camera)
      },
      onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight
        // 更新投影矩阵
        this.camera.updateProjectionMatrix()
        this.renderer.setSize(window.innerWidth, window.innerHeight)
      },
      // 相机控件
      createControls() {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement)
        // 增加平移速度
        this.controls.panSpeed = 2.0;
        // 增加缩放速度
        this.controls.zoomSpeed = 1.2;
        // 增加旋转速度
        this.controls.rotateSpeed = 1.0;

        // 禁用阻尼效果
        this.controls.enableDamping = false;
        // 禁用惯性效果
        this.controls.enableInertia = false;

        // 设置平移限制
        this.controls.maxPolarAngle = Math.PI; // 允许完全垂直旋转
        this.controls.minAzimuthAngle = -Infinity;
        this.controls.maxAzimuthAngle = Infinity;

        this.controls.addEventListener('change', () => {
          this.renderer.render(this.scene, this.camera)
        })
      }
    },
    unmounted() {
      window.removeEventListener('resize', this.onWindowResize)
      // if (this.renderer) {
      //   this.renderer.dispose()
      //   this.$refs.canvasContainer.removeChild(this.renderer.domElement)
      // }
    }
  };
</script>

<style lang="scss">
  * {
    margin: 0;
    padding: 0;
  }
</style>